home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / System7 tools / Frontier / Frontier SDK 2.1 / Toolkits / Applet Toolkit / appletfiles.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-09  |  13.1 KB  |  661 lines  |  [TEXT/KAHL]

  1.  
  2. /*© Copyright 1988-1992 UserLand Software, Inc.  All Rights Reserved.*/
  3.  
  4.  
  5. #include "appletops.h"
  6. #include "appletstrings.h"
  7. #include "appletmemory.h"
  8. #include "appletcursor.h"
  9. #include "appletdialogs.h"
  10. #include "appletfiles.h"
  11.  
  12.  
  13. static boolean foldertest (CInfoPBRec *pb) {
  14.     
  15.     /*
  16.     return true if pb holds info describing a folder.
  17.     */
  18.     
  19.     return (BitTst (&pb->dirInfo.ioFlAttrib, 3));
  20.     } /*foldertest*/
  21.  
  22.  
  23. static boolean getinfofrompb (CInfoPBRec *ppb, tyfileinfo *info) {
  24.     
  25.     CInfoPBRec pb = *ppb;
  26.     boolean flfolder;
  27.     
  28.     (*info).fllocked = BitTst (&pb.dirInfo.ioFlAttrib, 7);
  29.     
  30.     flfolder = (*info).flfolder = foldertest (&pb);
  31.     
  32.     if (flfolder) {
  33.         
  34.         (*info).flbusy = pb.dirInfo.ioDrNmFls > 0;
  35.         
  36.         (*info).filecreator = (*info).filetype = '    ';
  37.         
  38.         (*info).timecreated = pb.dirInfo.ioDrCrDat;
  39.  
  40.         (*info).timemodified = pb.dirInfo.ioDrMdDat;
  41.         
  42.         (*info).iconposition = pb.dirInfo.ioDrUsrWds.frLocation;
  43.         }
  44.         
  45.     else { /*fill in fields for a file, somewhat different format than a folder*/
  46.     
  47.         (*info).flbusy = BitTst (&pb.hFileInfo.ioFlAttrib, 0);
  48.         
  49.         (*info).flbundle = (pb.hFileInfo.ioFlFndrInfo.fdFlags & 0x2000) != 0;
  50.         
  51.         (*info).flinvisible = (pb.hFileInfo.ioFlFndrInfo.fdFlags & 0x4000) != 0;
  52.         
  53.         (*info).flalias = (pb.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) != 0;
  54.         
  55.         (*info).filecreator = pb.hFileInfo.ioFlFndrInfo.fdCreator;
  56.         
  57.         (*info).filetype = pb.hFileInfo.ioFlFndrInfo.fdType;
  58.         
  59.         (*info).timecreated = pb.hFileInfo.ioFlCrDat;
  60.  
  61.         (*info).timemodified = pb.hFileInfo.ioFlMdDat;
  62.         
  63.         (*info).sizedatafork = pb.hFileInfo.ioFlLgLen;
  64.         
  65.         (*info).sizeresourcefork = pb.hFileInfo.ioFlRLgLen;
  66.         
  67.         (*info).iconposition = pb.hFileInfo.ioFlFndrInfo.fdLocation;
  68.         }
  69.     
  70.     (*info).ixlabel = (pb.hFileInfo.ioFlFndrInfo.fdFlags & 0x000E) >> 1;
  71.     
  72.     return (true);
  73.     } /*getinfofrompb*/
  74.     
  75.     
  76. boolean filegetinfo (bigstring fname, short vnum, tyfileinfo *info) {
  77.     
  78.     CInfoPBRec pb;
  79.     
  80.     clearbytes (&pb, longsizeof (pb)); /*init all fields to zero*/
  81.     
  82.     pb.hFileInfo.ioNamePtr = fname;
  83.  
  84.     pb.hFileInfo.ioVRefNum = vnum;
  85.     
  86.     (*info).errcode = PBGetCatInfo (&pb, false);
  87.     
  88.     if ((*info).errcode != noErr)
  89.         return (false);
  90.         
  91.     clearbytes (info, longsizeof (tyfileinfo)); /*init all fields to zero*/
  92.     
  93.     copystring (fname, (*info).fname);
  94.     
  95.     getinfofrompb (&pb, info);
  96.     
  97.     return (true);
  98.     } /*filegetinfo*/
  99.     
  100.     
  101. boolean filedelete (bigstring bspath, short vnum) {
  102.  
  103.     HParamBlockRec pb;
  104.     
  105.     clearbytes (&pb, longsizeof (pb));
  106.     
  107.     pb.ioParam.ioNamePtr = bspath;
  108.     
  109.     pb.ioParam.ioVRefNum = vnum; 
  110.     
  111.     return (PBHDelete (&pb, false) == noErr);
  112.     } /*filedelete*/
  113.     
  114.  
  115. void fileclose (short fnum) {
  116.     
  117.     if (fnum != 0)
  118.         FSClose (fnum);
  119.     } /*fileclose*/
  120.     
  121.  
  122. boolean fileseteof (short fnum, long eof) {
  123.     
  124.     OSErr errcode;
  125.     
  126.     if (fnum != 0) {
  127.     
  128.         errcode = SetEOF (fnum, eof);
  129.         
  130.         return (errcode == noErr);
  131.         }
  132.         
  133.     return (true);
  134.     } /*fileseteof*/
  135.     
  136.  
  137. boolean fileopenorcreate (bigstring bs, short vnum, OSType creator, OSType filetype, short *fnum) {
  138.     
  139.     /*
  140.     open or create a file indicated by bs and vnum.  if bs is a full path, 
  141.     set vnum to 0.  return with fnum set to the Mac filesystem's file number
  142.     for the file.
  143.     
  144.     if we open a file, we takes what we get in the creator and filetype department.
  145.     however, if we create a file it's of the indicated filetype and creator.
  146.     */
  147.     
  148.     if (FSOpen (bs, vnum, fnum) == noErr) /*file exists and is open*/
  149.         return (true);
  150.     
  151.     if (Create (bs, vnum, creator, filetype) != noErr)
  152.         return (false);
  153.     
  154.     if (FSOpen (bs, vnum, fnum) != noErr) {
  155.     
  156.         FSClose (*fnum);
  157.             
  158.         filedelete (bs, vnum);
  159.         
  160.         return (false); /*failed to open the file for writing*/
  161.         }
  162.     
  163.     return (true);
  164.     } /*fileopenorcreate*/
  165.     
  166.     
  167. boolean fileopen (bigstring bs, short vnum, short *fnum) {
  168.     
  169.     register OSErr ec;
  170.     
  171.     ec = FSOpen (bs, vnum, fnum);
  172.     
  173.     return (ec == noErr);
  174.     } /*fileopen*/
  175.     
  176.     
  177. boolean filenew (bigstring bsfname, short vnum, OSType creator, OSType filetype, short *fnum) {
  178.     
  179.     register OSErr errcode;
  180.     
  181.     if (FSOpen (bsfname, vnum, fnum) == noErr) { /*file exists, delete it*/
  182.     
  183.         FSClose (*fnum);
  184.     
  185.         filedelete (bsfname, vnum);
  186.         }
  187.         
  188.     errcode = Create (bsfname, vnum, creator, filetype);
  189.         
  190.     if (oserror (errcode)) /*failed to open the file for writing*/
  191.         return (false);
  192.     
  193.     errcode = FSOpen (bsfname, vnum, fnum);
  194.     
  195.     if (oserror (errcode)) {
  196.     
  197.         FSClose (*fnum);
  198.             
  199.         filedelete (bsfname, vnum);
  200.         
  201.         return (false); /*failed to open the file for writing*/
  202.         }
  203.         
  204.     return (true); /*file exists and its open*/
  205.     } /*filenew*/
  206.     
  207.     
  208. boolean filetruncate (short fnum) {
  209.     
  210.     return (SetEOF (fnum, 0) == noErr);
  211.     } /*filetruncate*/
  212.  
  213.  
  214. long filegetsize (short fnum) {
  215.     
  216.     /*
  217.     get the size of a file that's already open.
  218.     */
  219.     
  220.     long filesize;
  221.     
  222.     if (GetEOF (fnum, &filesize) != noErr)
  223.         filesize = 0;
  224.     
  225.     return (filesize);
  226.     } /*filegetsize*/
  227.  
  228.  
  229. boolean filewrite (short fnum, long ctwrite, void *buffer) {
  230.     
  231.     /*
  232.     write ctwrite bytes from buffer to the current position in file number
  233.     fnum.  return true iff successful.
  234.     */
  235.  
  236.     if (ctwrite > 0) 
  237.  
  238.         if (FSWrite (fnum, &ctwrite, buffer) != noErr)
  239.         
  240.             return (false);
  241.     
  242.     return (true);
  243.     } /*filewrite*/
  244.     
  245.     
  246. boolean fileread (short fnum, long ctread, void *buffer) {
  247.     
  248.     /*
  249.     read ctread bytes from the current position in file number fnum into
  250.     the buffer.  return true iff successful.
  251.     */
  252.  
  253.     if (ctread > 0)
  254.         
  255.         if (oserror (FSRead (fnum, &ctread, buffer)))
  256.         
  257.             return (false);
  258.             
  259.     return (true);
  260.     } /*fileread*/
  261.     
  262.     
  263. boolean filegetchar (short fnum, byte *buffer) {
  264.     
  265.     /*
  266.     read the next character from the indicated file, returning it in *buffer.
  267.     
  268.     return false if we're at the end of the file, without triggering an error
  269.     dialog.
  270.     */
  271.     
  272.     long fpos, eof;
  273.     
  274.     if (GetFPos (fnum, &fpos) != noErr)
  275.         return (false);
  276.     
  277.     if (GetEOF (fnum, &eof) != noErr)
  278.         return (false);
  279.     
  280.     if (fpos == eof)
  281.         return (false);
  282.     
  283.     if (!fileread (fnum, 1L, buffer))
  284.         return (false);
  285.         
  286.     return (true);
  287.     } /*filegetchar*/
  288.     
  289.     
  290. boolean filewritehandle (short fnum, Handle h) {
  291.     
  292.     /*
  293.     write the indicated handle to the open file indicated by fnum at the
  294.     current position in the file.
  295.     */
  296.     
  297.     return (filewrite (fnum, GetHandleSize (h), *h));
  298.     } /*filewritehandle*/
  299.     
  300.     
  301. boolean filereadhandle (short fnum, long ctbytes, Handle *hreturned) {
  302.     
  303.     Handle h;
  304.     boolean fl;
  305.     
  306.     if (!newclearhandle (ctbytes, hreturned))
  307.         return (false);
  308.         
  309.     h = *hreturned; /*copy into register*/
  310.     
  311.     lockhandle (h);
  312.     
  313.     fl = fileread (fnum, ctbytes, *h);
  314.     
  315.     unlockhandle (h);
  316.         
  317.     if (!fl) {
  318.         
  319.         disposehandle (h);
  320.         
  321.         *hreturned = nil;
  322.         
  323.         return (false);
  324.         }
  325.         
  326.     return (true);
  327.     } /*filereadhandle*/    
  328.  
  329.  
  330. boolean filereadwholefile (short fnum, Handle *hreturned) {
  331.     
  332.     /*
  333.     load the whole file into memory, return true if it worked, with
  334.     the handle holding all the data from the file.
  335.     */
  336.     
  337.     return (filereadhandle (fnum, filegetsize (fnum), hreturned));
  338.     } /*filereadwholefile*/
  339.  
  340.     
  341. boolean fileparsevolname (bspath, vnum) bigstring bspath; short *vnum; {
  342.     
  343.     /*
  344.     convert a full path, which might contain a volume name at the beginning
  345.     to a path with no volume name, and it's associated volume number in vnum.
  346.     
  347.     example: "Rover™:MORE Work" will return with bspath = "MORE Work" and
  348.     vnum = -2 (the Macintosh vrefnum for the second mounted drive).  
  349.     
  350.     this combination of information plugs nicely into a lot of the file 
  351.     manager routines.
  352.     */
  353.     
  354.     short ix = 1;
  355.     bigstring bsvolname;
  356.     HParamBlockRec pb;
  357.     short vrefnum;
  358.     bigstring bs;
  359.     
  360.     copystring (bspath, bs); /*work on a copy*/
  361.     
  362.     if (isemptystring (bs))
  363.         return (false);
  364.     
  365.     if (!scanstring (':', bs, &ix)) { /*no colon, the whole thing is a volname*/
  366.     
  367.         copystring (bs, bsvolname);
  368.         
  369.         pushchar (':', bsvolname);
  370.         
  371.         setemptystring (bs);
  372.         }
  373.     else {
  374.         midstring (bs, 1, ix, bsvolname); /*pick off the vol name and the colon*/
  375.         
  376.         deletestring (bs, 1, ix);
  377.         }
  378.     
  379.     clearbytes (&pb, longsizeof (pb));
  380.     
  381.     pb.volumeParam.ioNamePtr = bsvolname;
  382.     
  383.     pb.volumeParam.ioVolIndex = -1; /*force him to use the name pointer only*/
  384.     
  385.     if (PBGetVInfo ((ParmBlkPtr) &pb, false) != noErr)
  386.         return (false);
  387.     
  388.     *vnum = pb.volumeParam.ioVRefNum;
  389.     
  390.     return (true);
  391.     } /*fileparsevolname*/
  392.  
  393.  
  394. boolean filefrompath (path, fname) bigstring path, fname; {
  395.     
  396.     /*
  397.     return all the characters to the right of the last colon in the path.
  398.     
  399.     example: "Work Disk #1:MORE Work:Status Center" returns "Status Center".
  400.     */
  401.     
  402.     bigstring bs;
  403.     short len;
  404.     boolean flpushcolon = false;
  405.     
  406.     copystring (path, bs); /*work on a copy, we might modify it*/
  407.     
  408.     len = stringlength (bs);
  409.     
  410.     if (len <= 0) {
  411.     
  412.         setstringlength (fname, 0);
  413.     
  414.         return (true);
  415.         }
  416.         
  417.     if (bs [len] == ':') {
  418.     
  419.         setstringlength (bs, len - 1);
  420.         
  421.         flpushcolon = true;
  422.         }
  423.     
  424.     lastword (bs, ':', fname);
  425.     
  426.     if (flpushcolon)
  427.         pushchar (':', fname);
  428.         
  429.     return (true);
  430.     } /*filefrompath*/
  431.     
  432.     
  433. boolean folderfrompath (path, folder) bigstring path, folder; {
  434.     
  435.     /*
  436.     return all the characters to the left of the colon, and the colon.
  437.     
  438.     example: "Work Disk #1:MORE Work:Status Center" returns "Work Disk #1:MORE Work:".
  439.     */
  440.     
  441.     bigstring bs;
  442.     
  443.     lastword (path, ':', bs); /*kind of inefficient, but ensures symmetry*/
  444.     
  445.     copystring (path, folder);
  446.     
  447.     setstringlength (folder, stringlength (folder) - stringlength (bs));
  448.     
  449.     return (true);
  450.     } /*folderfrompath*/
  451.     
  452.     
  453. boolean pathtofileinfo (path, fname, vnum) bigstring path, fname; short *vnum; {
  454.     
  455.     /*
  456.     convert a Macintosh file path into a file name and a volume number.
  457.     
  458.     we also get the directory id of the parent directory, primarily because we
  459.     have the code here, it supposedly works, and we might need it someday.
  460.     */
  461.     
  462.     CInfoPBRec pb;
  463.     bigstring folder;
  464.     long idparent;
  465.     
  466.     if (!fileparsevolname (path, vnum)) /*no volume specified*/
  467.         return (false);
  468.     
  469.     folderfrompath (path, folder);
  470.     
  471.     filefrompath (path, fname);
  472.     
  473.     clearbytes (&pb, longsizeof (pb));
  474.     
  475.     pb.dirInfo.ioNamePtr = folder;
  476.     
  477.     if (PBGetCatInfo (&pb,false) != noErr)
  478.         return (false);
  479.     
  480.     if (BitTst (&pb.hFileInfo.ioFlAttrib, 3)) /*it's a folder*/
  481.         idparent = pb.dirInfo.ioDrDirID;
  482.     else
  483.         idparent = pb.hFileInfo.ioFlParID;
  484.     
  485.     return (true);
  486.     } /*pathtofileinfo*/
  487.     
  488.     
  489. boolean directorytopath (long DirID, short vnum, bigstring path) {
  490.     
  491.     CInfoPBRec block;
  492.     bigstring bsdirectory;
  493.     OSErr errcode;
  494.     
  495.     setemptystring (path);
  496.     
  497.     clearbytes (&block, longsizeof (block));
  498.     
  499.     block.dirInfo.ioNamePtr = bsdirectory;
  500.     
  501.     block.dirInfo.ioDrParID = DirID;
  502.     
  503.     do {
  504.         block.dirInfo.ioVRefNum = vnum;
  505.         
  506.         block.dirInfo.ioFDirIndex = -1;
  507.         
  508.         block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
  509.         
  510.         errcode = PBGetCatInfo(&block,false);
  511.         
  512.         if (errcode != noErr)
  513.             return (false);
  514.         
  515.         if (!pushchar (':', bsdirectory))
  516.             return (false);
  517.             
  518.         if (!pushstring (path, bsdirectory))
  519.             return (false);
  520.         
  521.         copystring (bsdirectory, path);
  522.         } while (block.dirInfo.ioDrDirID != fsRtDirID);
  523.     
  524.     return (true);
  525.     } /*directorytopath*/
  526.  
  527.  
  528. static boolean PathNameFromWD (long vnum, bigstring path) {
  529.     
  530.     /*
  531.     PBGetWDInfo has a bug under A/UX 1.1.  If vnum is a real vnum
  532.     and not a wdRefNum, then it returns garbage.  Since A/UX has only 1
  533.     volume (in the Macintosh sense) and only 1 root directory, this can
  534.     occur only when a file has been selected in the root directory (/).
  535.     So we look for this and hard code the DirID and vnum. 
  536.     */
  537.     
  538.     WDPBRec block;
  539.     
  540.     clearbytes (&block, longsizeof (block));
  541.     
  542.     block.ioVRefNum = vnum;
  543.     
  544.     PBGetWDInfo (&block,false);
  545.     
  546.     return (directorytopath (block.ioWDDirID,block.ioWDVRefNum,path));
  547.     } /*PathNameFromWD*/
  548.     
  549.     
  550. boolean fileinfotopath (bigstring fname, short vnum, bigstring path) {
  551.     
  552.     setemptystring (path);
  553.         
  554.     if (!PathNameFromWD ((long) vnum, path)) 
  555.         return (false);
  556.         
  557.     pushstring (fname, path);
  558.     
  559.     return (true);
  560.     } /*fileinfotopath*/
  561.     
  562.     
  563. static sfcallback sfglobalfilter = nil;
  564.  
  565.  
  566. static pascal Boolean sffilter (CInfoPBRec *pb) {
  567.     
  568.     /*
  569.     if we return true, the file is filtered, meaning it is not included in the
  570.     standard file dialog list.
  571.     */
  572.     
  573.     tyfileinfo info;
  574.     
  575.     if (sfglobalfilter == nil)
  576.         return (-1);
  577.         
  578.     clearbytes (&info, longsizeof (tyfileinfo)); /*init all fields to zero*/
  579.     
  580.     copystring ((*pb).hFileInfo.ioNamePtr, info.fname);
  581.     
  582.     getinfofrompb (pb, &info);
  583.     
  584.     if ((*sfglobalfilter) (&info))
  585.         return (-1);
  586.         
  587.     return (0);
  588.     } /*sffilter*/
  589.  
  590.     
  591. boolean sfdialog (boolean flput, bigstring fname, short *vnum, sfcallback filterproc, OSType filetype) {
  592.     
  593.     register DialogTHndl hdialog;
  594.     register short id;
  595.     Rect r, rscreen;
  596.     Point pt;
  597.     SFReply reply;
  598.     SFTypeList typesrec;
  599.  
  600.     cometofront ();
  601.     
  602.     arrowcursor ();
  603.     
  604.     if (flput)
  605.         id = getDlgID;
  606.     else
  607.         id = putDlgID;
  608.         
  609.     hdialog = (DialogTHndl) GetResource ('DLOG', id);
  610.     
  611.     if (hdialog == nil) {
  612.         
  613.         pt.h = pt.v = 85;
  614.         }
  615.     else {
  616.         r = (**hdialog).boundsRect;
  617.     
  618.         rscreen = quickdrawglobal (screenBits).bounds;
  619.     
  620.         pt.h = rscreen.left + (((rscreen.right - rscreen.left) - (r.right - r.left)) / 2);
  621.     
  622.         pt.v = rscreen.top + ((rscreen.bottom - rscreen.top) - (r.bottom - r.top)) / 3;
  623.         }
  624.  
  625.     if (flput)
  626.         SFPutFile (pt, (ptrstring) "\p", fname, nil, &reply);
  627.         
  628.     else {
  629.         short ctfiles;
  630.         
  631.         if (filetype == 0) /*set filetype to 0 to get all files*/
  632.             ctfiles = -1;
  633.         else {
  634.             ctfiles = 1;
  635.             
  636.             typesrec [0] = filetype;
  637.             }
  638.         
  639.         if (filterproc == nil) {
  640.         
  641.             SFGetFile (pt, (ptrstring) "\p", nil, ctfiles, typesrec, nil, &reply);
  642.             }
  643.         else {    
  644.             sfglobalfilter = filterproc;
  645.         
  646.             SFGetFile (pt, (ptrstring) "\p", (FileFilterProcPtr) &sffilter, ctfiles, typesrec, nil, &reply);
  647.             }
  648.         }
  649.         
  650.     if (reply.good) {
  651.     
  652.         *vnum = reply.vRefNum;
  653.         
  654.         copystring (reply.fName, fname);
  655.         }
  656.         
  657.     return (reply.good);
  658.     } /*sfdialog*/
  659.             
  660.  
  661.